<!doctype html>
<html lang="zh-CN">
<head>

    <meta charset="utf-8">
    <meta name="generator" content="Hugo 0.74.1" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">

    <title>Go Flutter Desktop (一) 初探 | caijinglong的博客</title>
    <meta property="og:title" content="Go Flutter Desktop (一) 初探 - caijinglong的博客">
    <meta property="og:type" content="article">
        
    <meta property="article:published_time" content="2019-07-04T16:07:17&#43;08:00">
        
        
    <meta property="article:modified_time" content="2019-07-04T16:07:17&#43;08:00">
        
    <meta name="Keywords" content="golang,go语言,flutter,caijinglong,java,android,博客,项目管理,python,软件架构,公众号,小程序">
    <meta name="description" content="Go Flutter Desktop (一) 初探">
        
    <meta name="author" content="caijinglong">
    <meta property="og:url" content="http://www.kikt.top/posts/flutter/desktop/go-desktop-engine/flutter-go-desktop-1/">
    <link rel="shortcut icon" href="/favicon.ico" type="image/x-icon">

    <link rel="stylesheet" href="/css/normalize.css">
    
        <link rel="stylesheet" href="/css/prism.css">
    
    <link rel="stylesheet" href="/css/style.css">
    <script type="text/javascript" src="//cdn.bootcss.com/jquery/3.2.1/jquery.min.js"></script>

    

   
    <script>
        (function(){
            var bp = document.createElement('script');
            var curProtocol = window.location.protocol.split(':')[0];
            if (curProtocol === 'https') {
                bp.src = 'https://zz.bdstatic.com/linksubmit/push.js';
            }
            else {
                bp.src = 'http://push.zhanzhang.baidu.com/push.js';
            }
            var s = document.getElementsByTagName("script")[0];
            s.parentNode.insertBefore(bp, s);
        })();
    </script>

    
    
</head>

<body>
<header id="header" class="clearfix">
    <div class="container">
        <div class="col-group">
            <div class="site-name ">
                
                    <a id="logo" href="http://www.kikt.top">
                        caijinglong的博客
                    </a>
                
                <p class="description">Android/Flutter开发者，对于golang/python/ios/java 均有所了解</p>
            </div>
            <div>
                <nav id="nav-menu" class="clearfix">
                    <a class="" href="http://www.kikt.top">首页</a>
                    
                    <a  href="http://www.kikt.top/archives/" title="归档">归档</a>
                    
                    <a  href="http://www.kikt.top/contact/" title="接单">接单</a>
                    
                    <a  href="http://www.kikt.top/about/" title="关于">关于</a>
                    
                </nav>
            </div>
        </div>
    </div>
</header>


<div id="body">
    <div class="container">
        <div class="col-group">

            <div class="col-8" id="main">
                <div class="res-cons">
                    <article class="post">
                        <header>
                            <h1 class="post-title">Go Flutter Desktop (一) 初探</h1>
                        </header>
                        <date class="post-meta meta-date">
                            2019年7月4日
                        </date>
                        
                        <div class="post-meta meta-category">
                            |
                            
                                <a href="http://www.kikt.top/categories/flutter">flutter</a>
                            
                        </div>
                        
                        
                        <div class="post-meta">
                            <span id="busuanzi_container_page_pv">|<span id="busuanzi_value_page_pv"></span><span> 阅读</span></span>
                        </div>
                        
                        <div class="post-content">
                            <p>Flutter 在去年的时候就有一个第三方的桌面引擎, 是用 golang 开发的</p>
<p>Github 地址是:https://github.com/go-flutter-desktop/go-flutter</p>
<p>目前在 mac,linux,windows 均可用, 作为一个 mac 用户, 除了 retina 下字显得有点小, 感觉没有单独适配外, 总体感觉是优于官方的 desktop 引擎的</p>
<p>另外我是真实的 golang 脑残粉, 我觉得 golang 这东西真的太好了, 用 golang, 准不会错</p>
<ul>
<li><a href="#%E5%BC%80%E5%8F%91%E7%8E%AF%E5%A2%83">开发环境</a></li>
<li><a href="#%E7%8E%AF%E5%A2%83%E5%AE%89%E8%A3%85">环境安装</a>
<ul>
<li><a href="#go-%E8%AF%AD%E8%A8%80%E7%8E%AF%E5%A2%83%E5%AE%89%E8%A3%85">go 语言环境安装</a></li>
<li><a href="#go-flutter-%E7%9A%84%E7%8E%AF%E5%A2%83">go-flutter 的环境</a></li>
</ul>
</li>
<li><a href="#%E8%BF%90%E8%A1%8C-example">运行 example</a></li>
<li><a href="#%E5%B0%86%E5%8E%9F%E9%A1%B9%E7%9B%AE%E6%94%B9%E4%B8%BA-desktop">将原项目改为 desktop</a></li>
<li><a href="#%E6%B5%8B%E8%AF%95%E5%9F%BA%E7%A1%80%E7%9A%84%E9%A1%B9%E7%9B%AE">测试基础的项目</a>
<ul>
<li><a href="#%E4%BA%8B%E4%BB%B6%E5%93%8D%E5%BA%94">事件响应</a></li>
<li><a href="#ListView-%E6%BB%9A%E5%8A%A8">ListView 滚动</a></li>
<li><a href="#%E5%9B%BE%E7%89%87">图片</a>
<ul>
<li><a href="#%E7%BD%91%E7%BB%9C%E5%9B%BE%E7%89%87">网络图片</a></li>
<li><a href="#%E6%96%87%E4%BB%B6">文件</a></li>
<li><a href="#%E5%86%85%E5%AD%98">内存</a></li>
<li><a href="#%E8%B5%84%E4%BA%A7">资产</a></li>
</ul>
</li>
<li><a href="#%E8%BE%93%E5%85%A5%E6%A1%86">输入框</a>
<ul>
<li><a href="#%E8%BE%93%E5%85%A5%E5%93%8D%E5%BA%94">输入响应</a></li>
<li><a href="#%E6%98%BE%E7%A4%BA%E8%A1%8C%E4%B8%BA">显示行为</a></li>
<li><a href="#%E7%B3%BB%E7%BB%9F%E5%BF%AB%E6%8D%B7%E9%94%AE%E9%BC%A0%E6%A0%87%E8%A1%8C%E4%B8%BA">系统快捷键+鼠标行为</a></li>
</ul>
</li>
</ul>
</li>
<li><a href="#%E6%8F%92%E4%BB%B6">插件</a>
<ul>
<li><a href="#%E5%88%9B%E5%BB%BA%E5%B9%B6%E7%BC%96%E5%86%99%E6%8F%92%E4%BB%B6">创建并编写插件</a>
<ul>
<li><a href="#go-%E7%AB%AF">go 端</a></li>
<li><a href="#dart-%E7%AB%AF">dart 端</a></li>
</ul>
</li>
<li><a href="#%E5%8F%91%E5%B8%83%E6%8F%92%E4%BB%B6">发布插件</a></li>
<li><a href="#%E5%BC%95%E5%85%A5%E6%8F%92%E4%BB%B6">引入插件</a></li>
<li><a href="#%E8%BF%90%E8%A1%8C">运行</a></li>
</ul>
</li>
<li><a href="#%E5%90%8E%E8%AE%B0">后记</a></li>
</ul>
<h2 id="开发环境">开发环境</h2>
<p>需要的开发环境, 因为我是 MacOS, 我以 macOS 为例,其他的请参考对应的系统</p>
<ol>
<li>Xcode 命令行体系, 这个东西包含很多开发套件(Git), 无论你是否用 XCode 开发,都建议装一个&hellip;</li>
<li>Flutter 环境和配套工具, 这个跑不掉,作为 flutter 开发者&hellip;</li>
<li>go 语言环境(使用 brew 安装), 1.12+, IDE 用 Jetbrains 家的 goland (你用 VSCode 的话看你自己的情况)</li>
</ol>
<h2 id="环境安装">环境安装</h2>
<p>对 flutter 桌面版本感兴趣的一定接触过 flutter 开发, 我就默认你有 flutter 全套开发环境</p>
<h3 id="go-语言环境安装">go 语言环境安装</h3>
<p><code>$ brew install go</code></p>
<p>如果你的 go 比较老, 请升级,使用<code>$ brew upgrade go</code></p>
<p>配置 GOPATH 环境变量</p>
<p><code>$ vi ~/.bash_profile</code></p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-bash" data-lang="bash">export GOPATH<span style="color:#f92672">=</span>~/code/go <span style="color:#75715e"># 这个是必须配置的, 等号后的部分根据你的情况修改, 简单来说里面放的是你自己的代码,不是go的SDK,不是go的SDK,不是go的SDK, 具体的话是你 go 语言的三方库源码/自己写的go代码/中间产物/应用程序所在的目录</span>
PATH<span style="color:#f92672">=</span>$PATH:$GOPATH/bin  <span style="color:#75715e"># 这个是选配, 但是强烈建议配置,不然以后的go工具链需要全路径引用</span>
</code></pre></div><p>你下载的 go 相关的东西会被装在这个文件夹里</p>
<h3 id="go-flutter-的环境">go-flutter 的环境</h3>
<p>需要使用一个叫做 hover 的工具, 这个工具是由 go 编写的, 编译打包运行都使用这个工具</p>
<p><code>$ go get -u github.com/go-flutter-desktop/hover</code>, 这样这个工具会被安装到<code>$GOPATH/bin</code>目录下</p>
<p><img src="https://dev.azure.com/cjlspy/844861b8-ee45-48a3-b430-b974684baaaa/_apis/git/repositories/bf4da1c1-1cfa-4f54-8a75-745cce2b737c/items?versionDescriptor%5Bversion%5D=master&amp;path=%2F20190704163802.png&amp;versionDescriptor%5BversionOptions%5D=0&amp;versionDescriptor%5BversionType%5D=0&amp;resolveLfs=true&amp;%24format=octetStream&amp;api-version=5.0" alt="20190704163802.png"></p>
<p>当你可以直接在命令行输入 hover 可以出现如下情况时就说明可用了</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-bash" data-lang="bash">➜  ~ hover -h
Hover helps developers to release Flutter applications on desktop.

Usage:
  hover <span style="color:#f92672">[</span>flags<span style="color:#f92672">]</span>
  hover <span style="color:#f92672">[</span>command<span style="color:#f92672">]</span>

Available Commands:
  build       Build a desktop release
  help        Help about any command
  init        Initialize a flutter project to use go-flutter
  run         Build and start a desktop release, with hot-reload support

Flags:
  -h, --help   help <span style="color:#66d9ef">for</span> hover

Use <span style="color:#e6db74">&#34;hover [command] --help&#34;</span> <span style="color:#66d9ef">for</span> more information about a command.
➜  ~
</code></pre></div><p>安装 hover 出现问题的话可以参考<a href="https://github.com/go-flutter-desktop/hover#install">这里</a></p>
<h2 id="运行-example">运行 example</h2>
<p>官方提供了几个 example: <a href="https://github.com/go-flutter-desktop/examples.git">https://github.com/go-flutter-desktop/examples.git</a></p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-bash" data-lang="bash">cd /tmp
git clone https://github.com/go-flutter-desktop/examples.git flutter-examples
cd flutter-examples/pointer_demo
flutter pub get
hover run
</code></pre></div><p>通过以上几个步骤就可以把项目跑起来了</p>
<p><img src="https://dev.azure.com/cjlspy/844861b8-ee45-48a3-b430-b974684baaaa/_apis/git/repositories/bf4da1c1-1cfa-4f54-8a75-745cce2b737c/items?versionDescriptor%5Bversion%5D=master&amp;path=%2F20190704165918.png&amp;versionDescriptor%5BversionOptions%5D=0&amp;versionDescriptor%5BversionType%5D=0&amp;resolveLfs=true&amp;%24format=octetStream&amp;api-version=5.0" alt="20190704165918.png">
是一个关于鼠标移入移出监听的 demo</p>
<h2 id="将原项目改为-desktop">将原项目改为 desktop</h2>
<p>官方说明文档是这样的, 不想看英文的, 可以跳过官方文档直接看我的中文说明</p>
<p><img src="https://dev.azure.com/cjlspy/844861b8-ee45-48a3-b430-b974684baaaa/_apis/git/repositories/bf4da1c1-1cfa-4f54-8a75-745cce2b737c/items?versionDescriptor%5Bversion%5D=master&amp;path=%2F20190705150032.png&amp;versionDescriptor%5BversionOptions%5D=0&amp;versionDescriptor%5BversionType%5D=0&amp;resolveLfs=true&amp;%24format=octetStream&amp;api-version=5.0" alt="20190705150032.png"></p>
<p>这里要注意, 因为插件系统的原因, 如果不是纯 dart 插件, 则插件内容不能用</p>
<p>我模拟一下这个过程, 创建一个+++的 helloworld 工程, 你如果是要改造已有项目, 则应该 cd 到你的 flutter 的根目录进行 <code>$ hover init 项目url</code>的操作, 这里根据官方说, url 无所谓, 后面可改</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-bash" data-lang="bash">flutter create flutter_example_1
cd flutter_example_1
flutter pub get
hover init github.com/Caijinglong/flutter-go-example <span style="color:#75715e"># 初始化 desktop 工程</span>
</code></pre></div><p>这时候运行项目<code>$ hover run</code>会有一个提示: <code>Target file &quot;lib/main_desktop.dart&quot; not found.</code></p>
<p>我们查询可知, 可能是考虑到兼容性的问题, go 引擎的项目使用 <code>main_desktop.dart</code> 作为入口, 我们创建一个文件</p>
<p><code>main_desktop.dart</code>:</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-dart" data-lang="dart"><span style="color:#66d9ef">import</span> <span style="color:#e6db74">&#39;package:flutter/foundation.dart&#39;</span>;
<span style="color:#66d9ef">import</span> <span style="color:#e6db74">&#39;package:flutter/widgets.dart&#39;</span>;

<span style="color:#66d9ef">import</span> <span style="color:#e6db74">&#39;main.dart&#39;</span>;

<span style="color:#66d9ef">void</span> main() {
  debugDefaultTargetPlatformOverride <span style="color:#f92672">=</span> TargetPlatform.fuchsia;
  runApp(MyApp());
}

</code></pre></div><p><code>$ hover run</code></p>
<p><img src="https://dev.azure.com/cjlspy/844861b8-ee45-48a3-b430-b974684baaaa/_apis/git/repositories/bf4da1c1-1cfa-4f54-8a75-745cce2b737c/items?versionDescriptor%5Bversion%5D=master&amp;path=%2F20190704171705.png&amp;versionDescriptor%5BversionOptions%5D=0&amp;versionDescriptor%5BversionType%5D=0&amp;resolveLfs=true&amp;%24format=octetStream&amp;api-version=5.0" alt="20190704171705.png"></p>
<p>这样项目就跑起来了</p>
<h2 id="测试基础的项目">测试基础的项目</h2>
<p>测试下常用的几项:</p>
<ol>
<li>事件响应</li>
<li>ListView</li>
<li>图片</li>
<li>输入框情况</li>
</ol>
<h3 id="事件响应">事件响应</h3>
<p>点击事件是可行的,数字可加, 说明鼠标事件能响应, 其他的长按双击等等都是 flutter 实现的, 理论上就不需要测试了</p>
<p>最开始的官方 demo 中有鼠标移入移出事件</p>
<h3 id="listview-滚动">ListView 滚动</h3>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-dart" data-lang="dart"><span style="color:#66d9ef">import</span> <span style="color:#e6db74">&#39;package:flutter/material.dart&#39;</span>;

<span style="color:#66d9ef">class</span> <span style="color:#a6e22e">ListViewPage</span> <span style="color:#66d9ef">extends</span> StatefulWidget {
  <span style="color:#960050;background-color:#1e0010">@</span>override
  _ListViewPageState createState() <span style="color:#f92672">=&gt;</span> _ListViewPageState();
}

<span style="color:#66d9ef">class</span> <span style="color:#a6e22e">_ListViewPageState</span> <span style="color:#66d9ef">extends</span> State<span style="color:#f92672">&lt;</span>ListViewPage<span style="color:#f92672">&gt;</span> {
  <span style="color:#960050;background-color:#1e0010">@</span>override
  Widget build(BuildContext context) {
    <span style="color:#66d9ef">return</span> Scaffold(
      appBar: AppBar(),
      body: ListView.builder(
        itemBuilder: _buildItem,
      ),
    );
  }

  Widget _buildItem(BuildContext context, <span style="color:#66d9ef">int</span> index) {
    <span style="color:#66d9ef">return</span> ListTile(
      title: Text(index.toString()),
    );
  }
}

</code></pre></div><p><img src="https://dev.azure.com/cjlspy/844861b8-ee45-48a3-b430-b974684baaaa/_apis/git/repositories/bf4da1c1-1cfa-4f54-8a75-745cce2b737c/items?versionDescriptor%5Bversion%5D=master&amp;path=%2FKapture-2019-07-04-at-17.26.43.gif&amp;versionDescriptor%5BversionOptions%5D=0&amp;versionDescriptor%5BversionType%5D=0&amp;resolveLfs=true&amp;%24format=octetStream&amp;api-version=5.0" alt="Kapture 2019-07-04 at 17.26.43.gif"></p>
<p>没有移动端的惯性, 可以响应鼠标滚轮上下</p>
<p>改成横向的</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-dart" data-lang="dart">  Widget build(BuildContext context) {
    <span style="color:#66d9ef">return</span> Scaffold(
      appBar: AppBar(),
      body: ListView.builder(
        itemBuilder: _buildItem,
        scrollDirection: Axis.horizontal,
      ),
    );
  }
</code></pre></div><p>横向同样没惯性, shift+滚动可以横向</p>
<h3 id="图片">图片</h3>
<h4 id="网络图片">网络图片</h4>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-dart" data-lang="dart"><span style="color:#66d9ef">import</span> <span style="color:#e6db74">&#39;package:flutter/material.dart&#39;</span>;

<span style="color:#66d9ef">class</span> <span style="color:#a6e22e">ImagePage</span> <span style="color:#66d9ef">extends</span> StatefulWidget {
  <span style="color:#960050;background-color:#1e0010">@</span>override
  _ImagePageState createState() <span style="color:#f92672">=&gt;</span> _ImagePageState();
}

<span style="color:#66d9ef">class</span> <span style="color:#a6e22e">_ImagePageState</span> <span style="color:#66d9ef">extends</span> State<span style="color:#f92672">&lt;</span>ImagePage<span style="color:#f92672">&gt;</span> {
  <span style="color:#960050;background-color:#1e0010">@</span>override
  Widget build(BuildContext context) {
    <span style="color:#66d9ef">return</span> Scaffold(
      appBar: AppBar(),
      body: ListView(
        children: <span style="color:#f92672">&lt;</span>Widget<span style="color:#f92672">&gt;</span>[
          Container(
            width: <span style="color:#ae81ff">500</span>,
            height: <span style="color:#ae81ff">500</span>,
            child: Image.network(
                <span style="color:#e6db74">&#34;https://raw.githubusercontent.com/kikt-blog/image/master/img/20190704171705.png&#34;</span>),
          ),
        ],
      ),
    );
  }
}

</code></pre></div><p>网络图片可行</p>
<p><img src="https://dev.azure.com/cjlspy/844861b8-ee45-48a3-b430-b974684baaaa/_apis/git/repositories/bf4da1c1-1cfa-4f54-8a75-745cce2b737c/items?versionDescriptor%5Bversion%5D=master&amp;path=%2F20190704173327.png&amp;versionDescriptor%5BversionOptions%5D=0&amp;versionDescriptor%5BversionType%5D=0&amp;resolveLfs=true&amp;%24format=octetStream&amp;api-version=5.0" alt="20190704173327.png"></p>
<h4 id="文件">文件</h4>
<p>File 的图片, 直接使用本地图片就可以了, 我因为是 mac,所以是这样的,windows 可能是<code>c:\\XXXX\\XXX\\X.jpg</code></p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-dart" data-lang="dart">Container(
  width: <span style="color:#ae81ff">500</span>,
  height: <span style="color:#ae81ff">500</span>,
  child: Image.file(File(<span style="color:#e6db74">&#34;/Users/cai/Desktop/auto-angle.jpg&#34;</span>)),
),
</code></pre></div><p><img src="https://dev.azure.com/cjlspy/844861b8-ee45-48a3-b430-b974684baaaa/_apis/git/repositories/bf4da1c1-1cfa-4f54-8a75-745cce2b737c/items?versionDescriptor%5Bversion%5D=master&amp;path=%2F20190705092501.png&amp;versionDescriptor%5BversionOptions%5D=0&amp;versionDescriptor%5BversionType%5D=0&amp;resolveLfs=true&amp;%24format=octetStream&amp;api-version=5.0" alt="20190705092501.png"></p>
<h4 id="内存">内存</h4>
<p>memory , 这里需要模拟一下</p>
<p>读取上面的文件,然后转为 Uint8List</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-dart" data-lang="dart">Container(
  width: <span style="color:#ae81ff">500</span>,
  height: <span style="color:#ae81ff">500</span>,
  child: Image.memory(
    Uint8List.fromList(
      File(<span style="color:#e6db74">&#34;/Users/cai/Desktop/auto-angle.jpg&#34;</span>).readAsBytesSync(),
    ),
  ),
),
</code></pre></div><h4 id="资产">资产</h4>
<p>asset: 这种方式的加载我印象中去年这个引擎需要使用约定式文件夹, 与 flutter-web 的方式类似<br>
而现在不需要这种方式了, 直接与 flutter 官方的方式一致,只需要在 pubspec.yaml 中配置即可</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-yaml" data-lang="yaml"><span style="color:#66d9ef">flutter</span>:
  <span style="color:#75715e"># The following line ensures that the Material Icons font is</span>
  <span style="color:#75715e"># included with your application, so that you can use the icons in</span>
  <span style="color:#75715e"># the material Icons class.</span>
  <span style="color:#66d9ef">uses-material-design</span>: <span style="color:#66d9ef">true</span>

  <span style="color:#75715e"># To add assets to your application, add an assets section, like this:</span>
  <span style="color:#66d9ef">assets</span>:
    - assets/
</code></pre></div><p><img src="https://dev.azure.com/cjlspy/844861b8-ee45-48a3-b430-b974684baaaa/_apis/git/repositories/bf4da1c1-1cfa-4f54-8a75-745cce2b737c/items?versionDescriptor%5Bversion%5D=master&amp;path=%2F20190705102154.png&amp;versionDescriptor%5BversionOptions%5D=0&amp;versionDescriptor%5BversionType%5D=0&amp;resolveLfs=true&amp;%24format=octetStream&amp;api-version=5.0" alt="20190705102154.png"></p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-dart" data-lang="dart">Container(
  width: <span style="color:#ae81ff">500</span>,
  height: <span style="color:#ae81ff">500</span>,
  child: Image.asset(R.ASSETS_HAVE_EXIF_JPG),
),
</code></pre></div><div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-dart" data-lang="dart"><span style="color:#75715e">/// generate by resouce_generator library, shouldn&#39;t edit.
</span><span style="color:#75715e"></span><span style="color:#66d9ef">class</span> <span style="color:#a6e22e">R</span> {
  <span style="color:#75715e">/// ![preview](file:///private/tmp/flutter-go-example/./assets/have-exif.jpg)
</span><span style="color:#75715e"></span>  <span style="color:#66d9ef">static</span> <span style="color:#66d9ef">const</span> <span style="color:#66d9ef">String</span> ASSETS_HAVE_EXIF_JPG <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;assets/have-exif.jpg&#34;</span>;
}
</code></pre></div><p>这里插入一句, 图片会根据 exif 信息旋转至正确的方向
<img src="https://dev.azure.com/cjlspy/844861b8-ee45-48a3-b430-b974684baaaa/_apis/git/repositories/bf4da1c1-1cfa-4f54-8a75-745cce2b737c/items?versionDescriptor%5Bversion%5D=master&amp;path=%2F20190705102408.png&amp;versionDescriptor%5BversionOptions%5D=0&amp;versionDescriptor%5BversionType%5D=0&amp;resolveLfs=true&amp;%24format=octetStream&amp;api-version=5.0" alt="20190705102408.png"></p>
<p>但是图片多了后 ListView 的滚动性能似乎变差了</p>
<h3 id="输入框">输入框</h3>
<p>使用 Material 体系的 TextField 作为测试, Cupertino 和 Widget 体系的输入框请自行测试吧</p>
<p>有如下几个测试方向(有其他的需求可说, 我会加入)</p>
<ul>
<li>输入响应</li>
<li>显示行为</li>
<li>系统快捷键</li>
<li>鼠标行为</li>
</ul>
<h4 id="输入响应">输入响应</h4>
<p>这个很好理解, 就是用键盘能否输入字符&hellip; 因为 flutter 上的官方的 plugin 就没法输入(我都是道听途说)</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-dart" data-lang="dart"><span style="color:#66d9ef">import</span> <span style="color:#e6db74">&#39;package:flutter/material.dart&#39;</span>;

<span style="color:#66d9ef">class</span> <span style="color:#a6e22e">InputPage</span> <span style="color:#66d9ef">extends</span> StatefulWidget {
  <span style="color:#960050;background-color:#1e0010">@</span>override
  _InputPageState createState() <span style="color:#f92672">=&gt;</span> _InputPageState();
}

<span style="color:#66d9ef">class</span> <span style="color:#a6e22e">_InputPageState</span> <span style="color:#66d9ef">extends</span> State<span style="color:#f92672">&lt;</span>InputPage<span style="color:#f92672">&gt;</span> {
  <span style="color:#960050;background-color:#1e0010">@</span>override
  Widget build(BuildContext context) {
    <span style="color:#66d9ef">return</span> Scaffold(
      appBar: AppBar(title: Text(<span style="color:#e6db74">&#39;input&#39;</span>)),
      body: Container(
        child: TextField(),
      ),
    );
  }
}
</code></pre></div><p><img src="https://dev.azure.com/cjlspy/844861b8-ee45-48a3-b430-b974684baaaa/_apis/git/repositories/bf4da1c1-1cfa-4f54-8a75-745cce2b737c/items?versionDescriptor%5Bversion%5D=master&amp;path=%2F20190705102958.png&amp;versionDescriptor%5BversionOptions%5D=0&amp;versionDescriptor%5BversionType%5D=0&amp;resolveLfs=true&amp;%24format=octetStream&amp;api-version=5.0" alt="20190705102958.png"></p>
<p>输入英文还算正常</p>
<p>试试中文:</p>
<p><img src="https://dev.azure.com/cjlspy/844861b8-ee45-48a3-b430-b974684baaaa/_apis/git/repositories/bf4da1c1-1cfa-4f54-8a75-745cce2b737c/items?versionDescriptor%5Bversion%5D=master&amp;path=%2F20190705103106.png&amp;versionDescriptor%5BversionOptions%5D=0&amp;versionDescriptor%5BversionType%5D=0&amp;resolveLfs=true&amp;%24format=octetStream&amp;api-version=5.0" alt="20190705103106.png"></p>
<p>文字位置正常,输入框没跟随</p>
<h4 id="显示行为">显示行为</h4>
<p>单行没问题, 试试多行, 直接回车不行 我们需要将 TextField 设置为多行, 我这里分别设置 10/50 行</p>
<p><img src="https://dev.azure.com/cjlspy/844861b8-ee45-48a3-b430-b974684baaaa/_apis/git/repositories/bf4da1c1-1cfa-4f54-8a75-745cce2b737c/items?versionDescriptor%5Bversion%5D=master&amp;path=%2F20190705103327.png&amp;versionDescriptor%5BversionOptions%5D=0&amp;versionDescriptor%5BversionType%5D=0&amp;resolveLfs=true&amp;%24format=octetStream&amp;api-version=5.0" alt="20190705103327.png"></p>
<p>50 行的话,一页放不下,滚动也算正常
<img src="https://dev.azure.com/cjlspy/844861b8-ee45-48a3-b430-b974684baaaa/_apis/git/repositories/bf4da1c1-1cfa-4f54-8a75-745cce2b737c/items?versionDescriptor%5Bversion%5D=master&amp;path=%2FKapture-2019-07-05-at-10.34.23.gif&amp;versionDescriptor%5BversionOptions%5D=0&amp;versionDescriptor%5BversionType%5D=0&amp;resolveLfs=true&amp;%24format=octetStream&amp;api-version=5.0" alt="Kapture 2019-07-05 at 10.34.23.gif"></p>
<p>但是这里有一个问题, 中英文混合的情况下, 水滴不正常</p>
<p><img src="https://dev.azure.com/cjlspy/844861b8-ee45-48a3-b430-b974684baaaa/_apis/git/repositories/bf4da1c1-1cfa-4f54-8a75-745cce2b737c/items?versionDescriptor%5Bversion%5D=master&amp;path=%2F20190705103537.png&amp;versionDescriptor%5BversionOptions%5D=0&amp;versionDescriptor%5BversionType%5D=0&amp;resolveLfs=true&amp;%24format=octetStream&amp;api-version=5.0" alt="20190705103537.png"></p>
<p>开头和结尾都是英文则没问题, 都是中文同理
<img src="https://dev.azure.com/cjlspy/844861b8-ee45-48a3-b430-b974684baaaa/_apis/git/repositories/bf4da1c1-1cfa-4f54-8a75-745cce2b737c/items?versionDescriptor%5Bversion%5D=master&amp;path=%2F20190705103646.png&amp;versionDescriptor%5BversionOptions%5D=0&amp;versionDescriptor%5BversionType%5D=0&amp;resolveLfs=true&amp;%24format=octetStream&amp;api-version=5.0" alt="20190705103646.png">
<img src="https://dev.azure.com/cjlspy/844861b8-ee45-48a3-b430-b974684baaaa/_apis/git/repositories/bf4da1c1-1cfa-4f54-8a75-745cce2b737c/items?versionDescriptor%5Bversion%5D=master&amp;path=%2F20190705103635.png&amp;versionDescriptor%5BversionOptions%5D=0&amp;versionDescriptor%5BversionType%5D=0&amp;resolveLfs=true&amp;%24format=octetStream&amp;api-version=5.0" alt="20190705103635.png"></p>
<h4 id="系统快捷键鼠标行为">系统快捷键+鼠标行为</h4>
<p>常用的几个快捷键(复制,粘贴,全选)都是 OK 的, 基本行为和正常的输入框完全吻合,这里要给好评, 比官方桌面引擎好用多了, 其他系统的请自行测试</p>
<p><img src="https://dev.azure.com/cjlspy/844861b8-ee45-48a3-b430-b974684baaaa/_apis/git/repositories/bf4da1c1-1cfa-4f54-8a75-745cce2b737c/items?versionDescriptor%5Bversion%5D=master&amp;path=%2FKapture-2019-07-05-at-10.37.44.gif&amp;versionDescriptor%5BversionOptions%5D=0&amp;versionDescriptor%5BversionType%5D=0&amp;resolveLfs=true&amp;%24format=octetStream&amp;api-version=5.0" alt="Kapture 2019-07-05 at 10.37.44.gif"></p>
<p>鼠标行为顺便一起测试了,基本符合正常的操作习惯</p>
<h2 id="插件">插件</h2>
<p>这个版本的插件和官方的不一样, 需要用 golang 去写, 而不是各自平台的, 当然如果各自平台有特殊的 api, 也需要使用 golang 去调用</p>
<p>总体有如下几个步骤:</p>
<ol>
<li>创建插件</li>
<li>编写代码(go+dart)</li>
<li>引入插件</li>
</ol>
<p>官方文档在此: <a href="https://hover.build/docs/create-a-plugin/">https://hover.build/docs/create-a-plugin/</a></p>
<h3 id="创建并编写插件">创建并编写插件</h3>
<h4 id="go-端">go 端</h4>
<p>打开 goland, 或者其他的什么编辑器</p>
<p>具体的 golang 知识没法展开讲解,</p>
<p>可以理解为在 gopath 的 src 目录下创建一个包, 大部分情况下模仿别人, 建议放在 github.com 目录下</p>
<p><code>$ mkdir -p src/github.com/caijinglong/go-flutter-plugin/version</code></p>
<p>创建一个目录, 这个就是我插件的文件夹</p>
<p><code>version.go</code>:</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-go" data-lang="go"><span style="color:#f92672">package</span> <span style="color:#a6e22e">version</span>

<span style="color:#f92672">import</span> (
    <span style="color:#e6db74">&#34;github.com/go-flutter-desktop/go-flutter&#34;</span>
    <span style="color:#e6db74">&#34;github.com/go-flutter-desktop/go-flutter/plugin&#34;</span>
)

<span style="color:#66d9ef">const</span> (
    <span style="color:#a6e22e">channelName</span> = <span style="color:#e6db74">&#34;top.kikt/go/version&#34;</span>
    <span style="color:#a6e22e">getVersion</span>  = <span style="color:#e6db74">&#34;getVersion&#34;</span>
)

<span style="color:#66d9ef">type</span> <span style="color:#a6e22e">VersionPlugin</span> <span style="color:#66d9ef">struct</span>{}

<span style="color:#66d9ef">var</span> <span style="color:#a6e22e">_</span> <span style="color:#a6e22e">flutter</span>.<span style="color:#a6e22e">Plugin</span> = <span style="color:#f92672">&amp;</span><span style="color:#a6e22e">VersionPlugin</span>{}

<span style="color:#66d9ef">func</span> (<span style="color:#a6e22e">VersionPlugin</span>) <span style="color:#a6e22e">InitPlugin</span>(<span style="color:#a6e22e">messenger</span> <span style="color:#a6e22e">plugin</span>.<span style="color:#a6e22e">BinaryMessenger</span>) <span style="color:#66d9ef">error</span> {
    <span style="color:#a6e22e">channel</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">plugin</span>.<span style="color:#a6e22e">NewMethodChannel</span>(<span style="color:#a6e22e">messenger</span>, <span style="color:#a6e22e">channelName</span>, <span style="color:#a6e22e">plugin</span>.<span style="color:#a6e22e">StandardMethodCodec</span>{})
    <span style="color:#a6e22e">channel</span>.<span style="color:#a6e22e">HandleFunc</span>(<span style="color:#a6e22e">getVersion</span>, <span style="color:#a6e22e">getVersionFunc</span>)
    <span style="color:#66d9ef">return</span> <span style="color:#66d9ef">nil</span>;
}

<span style="color:#66d9ef">func</span> <span style="color:#a6e22e">getVersionFunc</span>(<span style="color:#a6e22e">arguments</span> <span style="color:#66d9ef">interface</span>{}) (<span style="color:#a6e22e">reply</span> <span style="color:#66d9ef">interface</span>{}, <span style="color:#a6e22e">err</span> <span style="color:#66d9ef">error</span>) {
    <span style="color:#66d9ef">return</span> <span style="color:#e6db74">&#34;0.0.1&#34;</span>, <span style="color:#66d9ef">nil</span>
}
</code></pre></div><p>这个文件就是我们的插件, 必须要有的是结构体声明, 初始化插件的方法</p>
<p>下面那个<code>getVersionFunc</code>就是我们处理的方法, 这里可以使用 golang 编程,返回你需要通过 golang 获取的数据或任何东西, 我这里返回了一个简单的字符串</p>
<h4 id="dart-端">dart 端</h4>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-dart" data-lang="dart"><span style="color:#66d9ef">import</span> <span style="color:#e6db74">&#39;package:flutter/services.dart&#39;</span>;

<span style="color:#66d9ef">class</span> <span style="color:#a6e22e">GetVersionPlugin</span> {
  <span style="color:#66d9ef">static</span> <span style="color:#66d9ef">const</span> _channel <span style="color:#f92672">=</span> <span style="color:#66d9ef">const</span> MethodChannel(<span style="color:#e6db74">&#34;top.kikt/go/version&#34;</span>);

  <span style="color:#66d9ef">static</span> Future<span style="color:#f92672">&lt;</span><span style="color:#66d9ef">String</span><span style="color:#f92672">&gt;</span> <span style="color:#66d9ef">get</span> version <span style="color:#66d9ef">async</span> <span style="color:#f92672">=&gt;</span> _channel.invokeMethod(<span style="color:#e6db74">&#34;getVersion&#34;</span>);
}
</code></pre></div><h3 id="发布插件">发布插件</h3>
<p>为了让我们的 flutter 应用可以找到这个插件, 需要一些配置</p>
<p>go-flutter 使用的是 go module 的方案管理的 go 包</p>
<p>我们需要如下几步</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-bash" data-lang="bash">cd $GOPATH/src/github.com/caijinglong/go-flutter-plugin/version
export GO111MODULE<span style="color:#f92672">=</span>on
go mod init github.com/caijinglong/go-flutter-plugin/version
go mod tidy
</code></pre></div><p>目前我们的目录结构是这样的</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-bash" data-lang="bash">/Users/cai/code/go/src/github.com/caijinglong/go-flutter-plugin/version
├── go.mod
├── go.sum
└── version.go
</code></pre></div><p>要想发布, 其实得发布到 github 上, 这样别人才能访问, 我们目前不这么做, 仅本地使用</p>
<h3 id="引入插件">引入插件</h3>
<p>这里需要修改 desktop/cmd 目录下的 options.go 文件</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-go" data-lang="go"><span style="color:#f92672">package</span> <span style="color:#a6e22e">main</span>

<span style="color:#f92672">import</span> (
    <span style="color:#e6db74">&#34;github.com/caijinglong/go-flutter-plugin/version&#34;</span>
    <span style="color:#e6db74">&#34;github.com/go-flutter-desktop/go-flutter&#34;</span>
)

<span style="color:#66d9ef">var</span> <span style="color:#a6e22e">options</span> = []<span style="color:#a6e22e">flutter</span>.<span style="color:#a6e22e">Option</span>{
    <span style="color:#a6e22e">flutter</span>.<span style="color:#a6e22e">WindowInitialDimensions</span>(<span style="color:#ae81ff">800</span>, <span style="color:#ae81ff">1280</span>),
    <span style="color:#a6e22e">flutter</span>.<span style="color:#a6e22e">AddPlugin</span>(<span style="color:#a6e22e">version</span>.<span style="color:#a6e22e">VersionPlugin</span>{}),
}
</code></pre></div><p>这时候重新运行下项目会报一个错</p>
<pre><code class="language-log" data-lang="log">build github.com/Caijinglong/flutter-go-example/desktop/cmd: cannot load github.com/caijinglong/go-flutter-plugin/version: cannot find module providing package github.com/caijinglong/go-flutter-plugin/version
</code></pre><p>这个是因为插件没有发布到 github 所致, 我们先在本地测试下, 需要按照官方文档修改一下</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-mod" data-lang="mod">module github.com<span style="color:#f92672">/</span>Caijinglong<span style="color:#f92672">/</span>flutter<span style="color:#f92672">-</span>go<span style="color:#f92672">-</span>example<span style="color:#f92672">/</span>desktop

go <span style="color:#ae81ff">1.12</span>

require (
  github.com<span style="color:#f92672">/</span>go<span style="color:#f92672">-</span>flutter<span style="color:#f92672">-</span>desktop<span style="color:#f92672">/</span>go<span style="color:#f92672">-</span>flutter v0.<span style="color:#ae81ff">24.1</span>
  github.com<span style="color:#f92672">/</span>pkg<span style="color:#f92672">/</span>errors v0.<span style="color:#ae81ff">8.1</span>
  .com<span style="color:#f92672">/</span>stretchr<span style="color:#f92672">/</span>objx v0.<span style="color:#ae81ff">2.0</span> <span style="color:#f92672">//</span> indirect
)

replace github.com<span style="color:#f92672">/</span>caijinglong<span style="color:#f92672">/</span>go<span style="color:#f92672">-</span>flutter<span style="color:#f92672">-</span>plugin<span style="color:#f92672">/</span>version <span style="color:#f92672">=&gt;</span> <span style="color:#f92672">/</span>Users<span style="color:#f92672">/</span>cai<span style="color:#f92672">/</span>code<span style="color:#f92672">/</span>go<span style="color:#f92672">/</span>src<span style="color:#f92672">/</span>github.com<span style="color:#f92672">/</span>caijinglong<span style="color:#f92672">/</span>go<span style="color:#f92672">-</span>flutter<span style="color:#f92672">-</span>plugin<span style="color:#f92672">/</span>version <span style="color:#f92672">//</span> <span style="color:#960050;background-color:#1e0010">添加这行</span>
</code></pre></div><p>接着就可以运行了</p>
<h3 id="运行">运行</h3>
<p><img src="https://dev.azure.com/cjlspy/844861b8-ee45-48a3-b430-b974684baaaa/_apis/git/repositories/bf4da1c1-1cfa-4f54-8a75-745cce2b737c/items?versionDescriptor%5Bversion%5D=master&amp;path=%2F20190705111417.png&amp;versionDescriptor%5BversionOptions%5D=0&amp;versionDescriptor%5BversionType%5D=0&amp;resolveLfs=true&amp;%24format=octetStream&amp;api-version=5.0" alt="20190705111417.png"></p>
<p>代码如下:</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-dart" data-lang="dart"><span style="color:#66d9ef">import</span> <span style="color:#e6db74">&#39;package:flutter/material.dart&#39;</span>;

<span style="color:#66d9ef">import</span> <span style="color:#e6db74">&#39;get_version_plugin.dart&#39;</span>;

<span style="color:#66d9ef">class</span> <span style="color:#a6e22e">PluginPage</span> <span style="color:#66d9ef">extends</span> StatefulWidget {
  <span style="color:#960050;background-color:#1e0010">@</span>override
  _PluginPageState createState() <span style="color:#f92672">=&gt;</span> _PluginPageState();
}

<span style="color:#66d9ef">class</span> <span style="color:#a6e22e">_PluginPageState</span> <span style="color:#66d9ef">extends</span> State<span style="color:#f92672">&lt;</span>PluginPage<span style="color:#f92672">&gt;</span> {
  <span style="color:#960050;background-color:#1e0010">@</span>override
  Widget build(BuildContext context) {
    <span style="color:#66d9ef">return</span> Scaffold(
      appBar: AppBar(),
      body: FutureBuilder<span style="color:#f92672">&lt;</span><span style="color:#66d9ef">String</span><span style="color:#f92672">&gt;</span>(
        future: GetVersionPlugin.version,
        builder: (c, snapshot) {
          <span style="color:#66d9ef">if</span> (<span style="color:#f92672">!</span>snapshot.hasData) {
            <span style="color:#66d9ef">return</span> Container();
          }
          <span style="color:#66d9ef">return</span> Text(snapshot.data);
        },
      ),
    );
  }
}
</code></pre></div><h2 id="后记">后记</h2>
<p>本章简单使用了一下 go-flutter 项目, 仓库地址: <a href="https://github.com/CaiJingLong/flutter-go-example">https://github.com/CaiJingLong/flutter-go-example</a></p>
<p>这里需要注意下, 由于 go 插件的原因,直接 clone 是跑不起来的, 你需要配置 go 以后, 把 go 插件复制到<code>$GOPATH/src/github.com/caijinglong/go-flutter-plugin/version</code>目录内</p>
<p>后面有时间补测下打包产物</p>
<p>以上</p>

                        </div>

                        

<div class="post-archive">
    <h2>See Also</h2>
    <ul class="listing">
        
        <li><a href="/posts/flutter/desktop/flutter-desktop-2/">Flutter Desktop Mac版(二) 插件初探</a></li>
        
        <li><a href="/posts/flutter/desktop/flutter-desktop-1/">Flutter Desktop Mac版(一) 初探</a></li>
        
        <li><a href="/posts/flutter/dart/generators/">dart中的生成器函数</a></li>
        
        <li><a href="/posts/flutter/exists/add-flutter-to-ios/">把flutter作为framework添加到已存在的iOS中</a></li>
        
        <li><a href="/posts/flutter/exists/android-as-aar-to-maven/">把flutter项目作为aar添加到已有的Android工程上</a></li>
        
    </ul>
</div>


                        <div class="post-meta meta-tags">
                            
                            <ul class="clearfix">
                                
                                <li><a href="http://www.kikt.top/tags/flutter">flutter</a></li>
                                
                                <li><a href="http://www.kikt.top/tags/desktop">desktop</a></li>
                                
                                <li><a href="http://www.kikt.top/tags/go">go</a></li>
                                
                            </ul>
                            
                        </div>
                    </article>
                    
    

    
    
    <div class="post bg-white">
      <script src="https://utteranc.es/client.js"
            repo= "caijinglong/kikt-blog-comment"
            issue-term="pathname"
            theme="github-light"
            crossorigin="anonymous"
            async>
      </script>
    </div>
    
                </div>
            </div>
            <div id="secondary">
    <section class="widget">
        <form id="search" action="//www.google.com/search" method="get" accept-charset="utf-8" target="_blank" _lpchecked="1">
      
      <input type="text" name="q" maxlength="20" placeholder="Search">
      <input type="hidden" name="sitesearch" value="http://www.kikt.top">
      <button type="submit" class="submit icon-search"></button>
</form>
    </section>
    
    <section class="widget">
        <h3 class="widget-title">最近文章</h3>
<ul class="widget-list">
    
    <li>
        <a href="http://www.kikt.top/posts/java/crack/crack1/" title="使用javassist,修改jar包方法实现">使用javassist,修改jar包方法实现</a>
    </li>
    
    <li>
        <a href="http://www.kikt.top/posts/github/actions/create/" title="Github action 的开发到发布">Github action 的开发到发布</a>
    </li>
    
    <li>
        <a href="http://www.kikt.top/posts/flutter/jenkins&#43;fastlane/" title="flutter Jenkins&#43;fastlane 自动化打测试包, 并上传蒲公英">flutter Jenkins&#43;fastlane 自动化打测试包, 并上传蒲公英</a>
    </li>
    
    <li>
        <a href="http://www.kikt.top/posts/go/compile-for-android/" title="编译 go 源码为 android 动态库(so)">编译 go 源码为 android 动态库(so)</a>
    </li>
    
    <li>
        <a href="http://www.kikt.top/posts/flutter/focusnode-2/" title="Flutter FocusNode 焦点那点事-(二)">Flutter FocusNode 焦点那点事-(二)</a>
    </li>
    
    <li>
        <a href="http://www.kikt.top/posts/flutter/focusnode-1/" title="Flutter FocusNode 焦点那点事-(一)">Flutter FocusNode 焦点那点事-(一)</a>
    </li>
    
    <li>
        <a href="http://www.kikt.top/posts/server/caddy/cros_for_local_dev/" title="用 Caddy 解决 web 开发中本地跨域的问题">用 Caddy 解决 web 开发中本地跨域的问题</a>
    </li>
    
    <li>
        <a href="http://www.kikt.top/posts/flutter/route/navigator-helper2/" title="Navigator Helper2">Navigator Helper2</a>
    </li>
    
    <li>
        <a href="http://www.kikt.top/posts/flutter/grey-app/" title="flutter 怎么实现app整体灰度">flutter 怎么实现app整体灰度</a>
    </li>
    
    <li>
        <a href="http://www.kikt.top/posts/flutter/plugin/flutter-sdk-import-aar/" title="Flutter 插件开发之引入aar到安卓部分 并使用本地maven">Flutter 插件开发之引入aar到安卓部分 并使用本地maven</a>
    </li>
    
</ul>
    </section>

    

    <section class="widget">
        <h3 class="widget-title">分类</h3>
<ul class="widget-list">
    
    <li>
        <a href="http://www.kikt.top/categories/android/">android(25)</a>
    </li>
    
    <li>
        <a href="http://www.kikt.top/categories/caddy/">caddy(1)</a>
    </li>
    
    <li>
        <a href="http://www.kikt.top/categories/dart/">dart(5)</a>
    </li>
    
    <li>
        <a href="http://www.kikt.top/categories/docker/">docker(3)</a>
    </li>
    
    <li>
        <a href="http://www.kikt.top/categories/flutter/">flutter(60)</a>
    </li>
    
    <li>
        <a href="http://www.kikt.top/categories/github/">github(3)</a>
    </li>
    
    <li>
        <a href="http://www.kikt.top/categories/go/">go(1)</a>
    </li>
    
    <li>
        <a href="http://www.kikt.top/categories/golang/">golang(1)</a>
    </li>
    
    <li>
        <a href="http://www.kikt.top/categories/iOS/">iOS(6)</a>
    </li>
    
    <li>
        <a href="http://www.kikt.top/categories/ios/">ios(1)</a>
    </li>
    
    <li>
        <a href="http://www.kikt.top/categories/java/">java(6)</a>
    </li>
    
    <li>
        <a href="http://www.kikt.top/categories/jetbrains/">jetbrains(1)</a>
    </li>
    
    <li>
        <a href="http://www.kikt.top/categories/other/">other(3)</a>
    </li>
    
    <li>
        <a href="http://www.kikt.top/categories/python/">python(1)</a>
    </li>
    
    <li>
        <a href="http://www.kikt.top/categories/server/">server(5)</a>
    </li>
    
    <li>
        <a href="http://www.kikt.top/categories/spring/">spring(3)</a>
    </li>
    
    <li>
        <a href="http://www.kikt.top/categories/tools/">tools(1)</a>
    </li>
    
    <li>
        <a href="http://www.kikt.top/categories/%E6%9D%82%E9%A1%B9/">杂项(1)</a>
    </li>
    
    <li>
        <a href="http://www.kikt.top/categories/%E6%B6%82%E9%B8%A6/">涂鸦(1)</a>
    </li>
    
</ul>
    </section>

    <section class="widget">
        <h3 class="widget-title">标签</h3>
<div class="tagcloud">
    
    <a href="http://www.kikt.top/tags/10/">10</a>
    
    <a href="http://www.kikt.top/tags/2.3/">2.3</a>
    
    <a href="http://www.kikt.top/tags/Clipboard/">Clipboard</a>
    
    <a href="http://www.kikt.top/tags/Javassist/">Javassist</a>
    
    <a href="http://www.kikt.top/tags/Migrate/">Migrate</a>
    
    <a href="http://www.kikt.top/tags/aar/">aar</a>
    
    <a href="http://www.kikt.top/tags/actions/">actions</a>
    
    <a href="http://www.kikt.top/tags/aidl/">aidl</a>
    
    <a href="http://www.kikt.top/tags/android/">android</a>
    
    <a href="http://www.kikt.top/tags/androidQ/">androidQ</a>
    
    <a href="http://www.kikt.top/tags/androidX/">androidX</a>
    
    <a href="http://www.kikt.top/tags/apk/">apk</a>
    
    <a href="http://www.kikt.top/tags/app/">app</a>
    
    <a href="http://www.kikt.top/tags/appcode/">appcode</a>
    
    <a href="http://www.kikt.top/tags/azure/">azure</a>
    
    <a href="http://www.kikt.top/tags/ble/">ble</a>
    
    <a href="http://www.kikt.top/tags/bottomsheet/">bottomsheet</a>
    
    <a href="http://www.kikt.top/tags/butterknife/">butterknife</a>
    
    <a href="http://www.kikt.top/tags/c/">c</a>
    
    <a href="http://www.kikt.top/tags/caddy/">caddy</a>
    
    <a href="http://www.kikt.top/tags/camera/">camera</a>
    
    <a href="http://www.kikt.top/tags/cameraX/">cameraX</a>
    
    <a href="http://www.kikt.top/tags/channel/">channel</a>
    
    <a href="http://www.kikt.top/tags/cocoapods/">cocoapods</a>
    
    <a href="http://www.kikt.top/tags/cupertino/">cupertino</a>
    
    <a href="http://www.kikt.top/tags/dart/">dart</a>
    
    <a href="http://www.kikt.top/tags/dart-2.6/">dart-2.6</a>
    
    <a href="http://www.kikt.top/tags/desktop/">desktop</a>
    
    <a href="http://www.kikt.top/tags/dialog/">dialog</a>
    
    <a href="http://www.kikt.top/tags/dmg/">dmg</a>
    
    <a href="http://www.kikt.top/tags/doc/">doc</a>
    
    <a href="http://www.kikt.top/tags/docker/">docker</a>
    
    <a href="http://www.kikt.top/tags/docker-compose/">docker-compose</a>
    
    <a href="http://www.kikt.top/tags/excel/">excel</a>
    
    <a href="http://www.kikt.top/tags/exists/">exists</a>
    
    <a href="http://www.kikt.top/tags/faq/">faq</a>
    
    <a href="http://www.kikt.top/tags/fastlane/">fastlane</a>
    
    <a href="http://www.kikt.top/tags/ffi/">ffi</a>
    
    <a href="http://www.kikt.top/tags/ffmpeg/">ffmpeg</a>
    
    <a href="http://www.kikt.top/tags/flexmark/">flexmark</a>
    
    <a href="http://www.kikt.top/tags/flutter/">flutter</a>
    
    <a href="http://www.kikt.top/tags/flutter-web/">flutter-web</a>
    
    <a href="http://www.kikt.top/tags/focus/">focus</a>
    
    <a href="http://www.kikt.top/tags/focusNode/">focusNode</a>
    
    <a href="http://www.kikt.top/tags/form/">form</a>
    
    <a href="http://www.kikt.top/tags/framework/">framework</a>
    
    <a href="http://www.kikt.top/tags/github/">github</a>
    
    <a href="http://www.kikt.top/tags/go/">go</a>
    
    <a href="http://www.kikt.top/tags/golang/">golang</a>
    
    <a href="http://www.kikt.top/tags/gradle/">gradle</a>
    
    <a href="http://www.kikt.top/tags/http/">http</a>
    
    <a href="http://www.kikt.top/tags/iOS/">iOS</a>
    
    <a href="http://www.kikt.top/tags/ide/">ide</a>
    
    <a href="http://www.kikt.top/tags/idea/">idea</a>
    
    <a href="http://www.kikt.top/tags/index/">index</a>
    
    <a href="http://www.kikt.top/tags/inside/">inside</a>
    
    <a href="http://www.kikt.top/tags/ios/">ios</a>
    
    <a href="http://www.kikt.top/tags/java/">java</a>
    
    <a href="http://www.kikt.top/tags/jenkins/">jenkins</a>
    
    <a href="http://www.kikt.top/tags/jetbrains/">jetbrains</a>
    
    <a href="http://www.kikt.top/tags/jsdelivr/">jsdelivr</a>
    
    <a href="http://www.kikt.top/tags/json/">json</a>
    
    <a href="http://www.kikt.top/tags/json_serializable/">json_serializable</a>
    
    <a href="http://www.kikt.top/tags/junit/">junit</a>
    
    <a href="http://www.kikt.top/tags/library/">library</a>
    
    <a href="http://www.kikt.top/tags/live-template/">live-template</a>
    
    <a href="http://www.kikt.top/tags/loadmore/">loadmore</a>
    
    <a href="http://www.kikt.top/tags/log/">log</a>
    
    <a href="http://www.kikt.top/tags/mac/">mac</a>
    
    <a href="http://www.kikt.top/tags/macos/">macos</a>
    
    <a href="http://www.kikt.top/tags/maven/">maven</a>
    
    <a href="http://www.kikt.top/tags/mysql/">mysql</a>
    
    <a href="http://www.kikt.top/tags/navigationbar/">navigationbar</a>
    
    <a href="http://www.kikt.top/tags/navigator/">navigator</a>
    
    <a href="http://www.kikt.top/tags/ndk/">ndk</a>
    
    <a href="http://www.kikt.top/tags/nginx/">nginx</a>
    
    <a href="http://www.kikt.top/tags/oc/">oc</a>
    
    <a href="http://www.kikt.top/tags/opencv/">opencv</a>
    
    <a href="http://www.kikt.top/tags/poi/">poi</a>
    
    <a href="http://www.kikt.top/tags/pub/">pub</a>
    
    <a href="http://www.kikt.top/tags/python/">python</a>
    
    <a href="http://www.kikt.top/tags/retrofit/">retrofit</a>
    
    <a href="http://www.kikt.top/tags/route/">route</a>
    
    <a href="http://www.kikt.top/tags/server/">server</a>
    
    <a href="http://www.kikt.top/tags/so/">so</a>
    
    <a href="http://www.kikt.top/tags/spp/">spp</a>
    
    <a href="http://www.kikt.top/tags/sprintboot/">sprintboot</a>
    
    <a href="http://www.kikt.top/tags/swift/">swift</a>
    
    <a href="http://www.kikt.top/tags/tap/">tap</a>
    
    <a href="http://www.kikt.top/tags/thymeleaf/">thymeleaf</a>
    
    <a href="http://www.kikt.top/tags/tips/">tips</a>
    
    <a href="http://www.kikt.top/tags/toast/">toast</a>
    
    <a href="http://www.kikt.top/tags/transition/">transition</a>
    
    <a href="http://www.kikt.top/tags/ui/">ui</a>
    
    <a href="http://www.kikt.top/tags/utf8/">utf8</a>
    
    <a href="http://www.kikt.top/tags/yield/">yield</a>
    
    <a href="http://www.kikt.top/tags/%E4%BA%8C%E8%BF%9B%E5%88%B6/">二进制</a>
    
    <a href="http://www.kikt.top/tags/%E4%BA%A4%E5%8F%89/">交叉</a>
    
    <a href="http://www.kikt.top/tags/%E4%BA%A4%E5%8F%89%E7%BC%96%E8%AF%91/">交叉编译</a>
    
    <a href="http://www.kikt.top/tags/%E4%BB%8B%E7%BB%8D/">介绍</a>
    
    <a href="http://www.kikt.top/tags/%E4%BB%A3%E7%A0%81%E8%A7%84%E8%8C%83/">代码规范</a>
    
    <a href="http://www.kikt.top/tags/%E5%86%B2%E7%AA%81/">冲突</a>
    
    <a href="http://www.kikt.top/tags/%E5%8A%A8%E6%80%81/">动态</a>
    
    <a href="http://www.kikt.top/tags/%E5%8F%91%E5%B8%83/">发布</a>
    
    <a href="http://www.kikt.top/tags/%E5%8F%AF%E6%89%A7%E8%A1%8C/">可执行</a>
    
    <a href="http://www.kikt.top/tags/%E5%9B%BE%E5%BA%8A/">图床</a>
    
    <a href="http://www.kikt.top/tags/%E5%9F%8E%E5%B8%82/">城市</a>
    
    <a href="http://www.kikt.top/tags/%E5%A4%A7%E6%96%87%E4%BB%B6/">大文件</a>
    
    <a href="http://www.kikt.top/tags/%E5%B7%A5%E5%85%B7/">工具</a>
    
    <a href="http://www.kikt.top/tags/%E5%B7%B2%E6%9C%89%E9%A1%B9%E7%9B%AE/">已有项目</a>
    
    <a href="http://www.kikt.top/tags/%E5%BC%80%E5%8F%91%E7%8E%AF%E5%A2%83/">开发环境</a>
    
    <a href="http://www.kikt.top/tags/%E6%80%BB%E7%BB%93/">总结</a>
    
    <a href="http://www.kikt.top/tags/%E6%85%A2/">慢</a>
    
    <a href="http://www.kikt.top/tags/%E6%89%93%E5%8C%85/">打包</a>
    
    <a href="http://www.kikt.top/tags/%E6%89%AB%E7%A0%81/">扫码</a>
    
    <a href="http://www.kikt.top/tags/%E6%8F%92%E4%BB%B6/">插件</a>
    
    <a href="http://www.kikt.top/tags/%E6%96%87%E6%A1%A3/">文档</a>
    
    <a href="http://www.kikt.top/tags/%E6%A8%A1%E6%9D%BF/">模板</a>
    
    <a href="http://www.kikt.top/tags/%E6%B8%B2%E6%9F%93/">渲染</a>
    
    <a href="http://www.kikt.top/tags/%E6%BA%90%E7%A0%81%E8%A7%A3%E6%9E%90/">源码解析</a>
    
    <a href="http://www.kikt.top/tags/%E7%81%B0%E5%BA%A6/">灰度</a>
    
    <a href="http://www.kikt.top/tags/%E7%82%B9%E5%87%BB/">点击</a>
    
    <a href="http://www.kikt.top/tags/%E7%84%A6%E7%82%B9/">焦点</a>
    
    <a href="http://www.kikt.top/tags/%E7%88%AC%E8%99%AB/">爬虫</a>
    
    <a href="http://www.kikt.top/tags/%E7%8A%B6%E6%80%81%E7%AE%A1%E7%90%86/">状态管理</a>
    
    <a href="http://www.kikt.top/tags/%E7%99%BE%E5%BA%A6%E5%9C%B0%E5%9B%BE/">百度地图</a>
    
    <a href="http://www.kikt.top/tags/%E7%BC%96%E7%A0%81/">编码</a>
    
    <a href="http://www.kikt.top/tags/%E7%BC%96%E7%A8%8B%E6%8A%80%E5%B7%A7/">编程技巧</a>
    
    <a href="http://www.kikt.top/tags/%E7%BC%96%E8%AF%91/">编译</a>
    
    <a href="http://www.kikt.top/tags/%E7%BF%BB%E8%AF%91/">翻译</a>
    
    <a href="http://www.kikt.top/tags/%E8%93%9D%E7%89%99/">蓝牙</a>
    
    <a href="http://www.kikt.top/tags/%E8%A1%A8%E5%8D%95/">表单</a>
    
    <a href="http://www.kikt.top/tags/%E8%B7%AF%E7%94%B1/">路由</a>
    
    <a href="http://www.kikt.top/tags/%E8%BF%87%E5%9C%BA%E5%8A%A8%E7%94%BB/">过场动画</a>
    
    <a href="http://www.kikt.top/tags/%E9%9A%90%E7%A7%81/">隐私</a>
    
</div>
    </section>

    
<section class="widget">
    <h3 class="widget-title">友情链接</h3>
    <ul class="widget-list">
        
        <li>
            <a target="_blank" href="https://github.com/Caijinglong" title="我的Github">我的Github</a>
        </li>
        
        <li>
            <a target="_blank" href="https://flutter.dev" title="flutter 官网">flutter 官网</a>
        </li>
        
    </ul>
</section>


    <section class="widget">
        <h3 class="widget-title">其它</h3>
        <ul class="widget-list">
            <li><a href="http://www.kikt.top/index.xml">文章 RSS</a></li>
        </ul>
    </section>
</div>
        </div>
    </div>
</div>
<footer id="footer">
    <div class="container">
        <div>
            <p>如果我的blog对您有帮助,而您愿意捐赠 😆, 可以用下面的二维码</p>
            <img style="width:5rem;" src="https://dev.azure.com/cjlspy/844861b8-ee45-48a3-b430-b974684baaaa/_apis/git/repositories/bf4da1c1-1cfa-4f54-8a75-745cce2b737c/items?versionDescriptor%5Bversion%5D=master&versionDescriptor%5BversionOptions%5D=0&versionDescriptor%5BversionType%5D=0&resolveLfs=true&%24format=octetStream&api-version=5.0&path=%2F20190424141834.png"/>
            <img style="width:5rem; padding-left: 2rem;" 
            src="https://dev.azure.com/cjlspy/844861b8-ee45-48a3-b430-b974684baaaa/_apis/git/repositories/bf4da1c1-1cfa-4f54-8a75-745cce2b737c/items?versionDescriptor%5Bversion%5D=master&versionDescriptor%5BversionOptions%5D=0&versionDescriptor%5BversionType%5D=0&resolveLfs=true&%24format=octetStream&api-version=5.0&path=%2F20190424141931.png"/>
            <img style="width:5rem; padding-left: 2rem;" 
            src="https://dev.azure.com/cjlspy/844861b8-ee45-48a3-b430-b974684baaaa/_apis/git/repositories/bf4da1c1-1cfa-4f54-8a75-745cce2b737c/items?versionDescriptor%5Bversion%5D=master&versionDescriptor%5BversionOptions%5D=0&versionDescriptor%5BversionType%5D=0&resolveLfs=true&%24format=octetStream&api-version=5.0&path=%2F20190424142013.png"/>
        </div>
        &copy; 2018 <a href="http://www.kikt.top">caijinglong的博客 By caijinglong</a>.
        Powered by <a rel="nofollow noreferer noopener" href="https://gohugo.io" target="_blank">Hugo</a>.
        <a href="http://www.flysnow.org/" target="_blank">Theme</a> based on <a href="https://github.com/rujews/maupassant-hugo" target="_blank">maupassant</a>.<br/>
        本站所有内容基于<a href="https://creativecommons.org/licenses/by-nc-sa/4.0/deed.zh" style="color:coral">CC4.0</a>协议发布,需要转载必须署名
        <br/>
        如果有问题可以<a href="mailto:cjl_spy@163.com">email联系我</a>
        <br/>
        京ICP备18038473号-1
        
    </div>
</footer>


    <script type="text/javascript" src="/js/prism.js" async="true"></script>
    <script type="text/javascript">
    
    (function(){
        $("pre code").parent().addClass("line-numbers")
    }())

    window.MathJax = {
        tex2jax: {
            inlineMath: [ ['$','$'] ],
            processEscapes: true
        }
    };
    </script>
    <script src='https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.5/MathJax.js?config=TeX-MML-AM_CHTML' async></script>

<a id="rocket" href="#top"></a>
<script type="text/javascript" src="/js/totop.js?v=0.0.0" async=""></script>



<script type="text/javascript" src="//busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js" async></script>




</body>
</html>
